from flask import (
    Flask,
    render_template,
    request,
    jsonify,
    stream_with_context,
)
import os
import uuid
import logging
from dotenv import load_dotenv
import pdfplumber
from docx import Document
import json
from openai import OpenAI
from database import get_db_session, Job, Result

load_dotenv()
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
app = Flask(__name__)
# 配置上传文件的保存目录
app.config["UPLOAD_DIR"] = os.getenv("UPLOAD_DIR", "uploads")
# 配置最大上传的文件大小阈值为10M
app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 10

if not os.path.exists(app.config["UPLOAD_DIR"]):
    os.makedirs(app.config["UPLOAD_DIR"])


def allowd_file(ext):
    return ext in {"pdf", "doxc"}


client = OpenAI(
    api_key=os.getenv("DEEPSEEK_API_KEY", ""), base_url="https://api.deepseek.com/v1"
)

PROMPT_TEMPLATE = """
请根据以下的职位描述和简历的内容，给出是否匹配的明确结论 是或者否

职位信息如下:{job_description}
简历信息如下:{resume_text}
请按以下的格式输出分析结果:
1.是否符合职位要求
2.说明匹配或不匹配的原因
3.技术能力分析
  - 已具备的技术点
  - 欠缺的技术点
4.改进建议
  - 具体的学习路径
  - 推荐的学习资源
  - 预计达到要求需要的时间周期
备注：请只关注技术能力方面的匹配度，忽略城市 、性别、学历等其它因素
"""


@app.route("/resume", methods=["GET"])
def resume():
    return render_template("resume.html")


def extract_resume_text(save_path, ext):
    text = ""
    if ext == "pdf":
        with pdfplumber.open(save_path) as pdf:
            text = "\n".join(page.extract_text() for page in pdf.pages)
    elif ext == "docx":
        text_list = []
        doc = Document(save_path)
        for para in doc.paragraphs:
            text_list.append(para.text)
        text = "\n".join(text_list)
    return text


@app.route("/analyze/stream", methods=["POST"])
def upload_resume_stream():
    if "resume" not in request.files:
        return jsonify({"success": False, "error": "未上传文件"})
    file = request.files["resume"]
    if file.name == "":
        return jsonify({"success": False, "error": "未上传文件"})

    ext = os.path.splitext(file.filename)[1].lower().lstrip(".")

    if not allowd_file(ext):
        return jsonify({"success": False, "error": "仅支持PDF和WORD文件"})

    # 声明一个保存的唯一的文件名
    filename = f"{uuid.uuid4().hex}.{ext}"
    # 指定保存的路径
    save_path = os.path.join(app.config["UPLOAD_DIR"], filename)
    # 把上传的文件保存在指定的路径中  save(file,save_path)
    file.save(save_path)

    def generate():
        try:
            resume_text = extract_resume_text(save_path, ext)
            with get_db_session() as session:
                # 查询所有的职位对象
                jobs = session.query(Job).limit(1).all()

                for job in jobs:
                    job_description = job.description
                    prompt = PROMPT_TEMPLATE.format(
                        job_description=job_description, resume_text=resume_text
                    )
                    response = client.chat.completions.create(
                        model="deepseek-chat",
                        messages=[
                            {
                                "role": "system",
                                "content": "你是一个负责"
                                + os.getenv("SEARCH_KEY", "AI前端")
                                + "招聘的技术专家",
                            },
                            {"role": "user", "content": prompt},
                        ],
                        stream=True,
                    )
                    yield f"data: " + json.dumps(
                        {
                            "job_id": job.id,
                            "job_name": job.job_name,
                            "company": job.company,
                            "type": "start",
                        },
                        ensure_ascii=False,
                    ) + "\n\n"
                    full_content = ""
                    for chunk in response:
                        if chunk.choices[0].delta.content:
                            # 获取大模型流式输出的内容
                            content = chunk.choices[0].delta.content
                            full_content += content
                            yield f"data: " + json.dumps(
                                {
                                    "job_id": job.id,
                                    "job_name": job.job_name,
                                    "company": job.company,
                                    "type": "content",
                                    "content": content,
                                },
                                ensure_ascii=False,
                            ) + "\n\n"
                    # 分析结果表数据
                    result_data = {
                        "job_id": job.job_id,
                        "file_path": save_path,
                        "result": full_content,
                    }
                    with get_db_session() as session:
                        result = (
                            session.query(Result)
                            .filter(Result.job_id == job.job_id)
                            .first()
                        )
                        # 如果职位有分析结果，更新
                        if result:
                            for key, value in result_data.items():
                                if hasattr(result, key) and key != "job_id":
                                    setattr(result, key, value)
                        # 如果没有职位分析结果，添加
                        else:
                            session.add(Result(**result_data))

                    yield f"data: " + json.dumps(
                        {
                            "job_id": job.id,
                            "job_name": job.job_name,
                            "company": job.company,
                            "type": "end",
                        },
                        ensure_ascii=False,
                    ) + "\n\n"
        except Exception as e:
            logger.error(f"简历分析失败:{e}")
            yield f"data: " + json.dumps(
                {
                    "type": "error",
                    "error": str(e),
                },
                ensure_ascii=False,
            ) + "\n\n"

    # 返回流式响应 设置MIME类型为事件流
    return app.response_class(
        stream_with_context(generate()), mimetype="text/event-stream"
    )


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5001)
